package com.come4loves.core.comunicate.codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.come4loves.core.comunicate.ComunicateConst;

public abstract class BaseDecoder extends ByteToMessageDecoder {
	protected Logger LOGGER = LoggerFactory.getLogger(getClass());
	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf in,
			List<Object> out) throws Exception {
		ByteBuf buff = in;
		int headError = 0;
		while (true) {//查找消息头
			if (headError >= 1024 * 5) {//查找5K字节找不到就抛出异常
				buff.resetReaderIndex();
				throw new MessageException("can't find pb head!");
			}
			if (buff.readableBytes() < 5) {
				return;
			}
			buff.markReaderIndex();
			int flag = in.readInt();
			if (flag == ComunicateConst.HEADER_FLAG) {
				break;
			}
			LOGGER.warn("pb head error:{}", flag);
			buff.resetReaderIndex();
			buff.readByte();//跳过一个字节
			headError += 1;
		}
		if (headError > 0) {
			LOGGER.warn(String.format("pb head error, address:[%s], skip [%s] bytes", ctx.channel().remoteAddress(), headError));
		}
		if (buff.readableBytes() < 4) {
			buff.resetReaderIndex();
			return;
		}
		
		int messageLen = buff.readInt();
		if (buff.readableBytes() < messageLen) {
			buff.resetReaderIndex();
			return;
		}
		
		Object object = decode(buff, messageLen);
		if (object != null) {
			out.add(object);
		}
		
	}
	
	protected abstract Object decode(ByteBuf in, int messageLen) throws Exception ;
	
	protected int cacleHashCode(byte[] data) {
		int seed = 0x1000193;
		int hash = 0x811c9dc5;
		int j = data.length;
		for (int i = 0; i < j; ++i) {
			byte b = data[i];
			hash = (hash ^ b) * seed;
		}

		hash += hash << 7;
		hash ^= hash >> 6;
		hash += hash << 3;
		hash ^= hash >> 8;
		hash += hash << 1;
		return hash;
	}

}
